// 
//  
//  Copyright (C) 2004-2009  Autodesk, Inc.
//  
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of version 2.1 of the GNU Lesser
//  General Public License as published by the Free Software Foundation.
//  
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//  
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//  
#include "stdafx.h"
#include "MapInfoConnection.h"
#include "MapInfoConnectionInfo.h"
#include "MapInfoProvider.h"

#include <FdoCommonConnPropDictionary.h>
#include <FdoCommonStringUtil.h>
#include <FdoCommonFile.h>
#include <FdoCommonOSUtil.h>
#include <FdoCommonConnStringParser.h>

//-------------------------------------------------------
// Constructor / destructor
//-------------------------------------------------------


// constructs a MapInfoConnectionInfo using the specified connection
MapInfoConnectionInfo::MapInfoConnectionInfo(MapInfoConnection* connection)
{
    m_connection = connection;
    // NOTE: don't addref the connection because we don't own
    //       it (rather, it owns us)
}


// default destructor
MapInfoConnectionInfo::~MapInfoConnectionInfo()
{
}


//-------------------------------------------------------
// FdoIDisposable implementation
//-------------------------------------------------------


// dispose this object
void MapInfoConnectionInfo::Dispose()
{
    delete this;
}


//-------------------------------------------------------
// FdoIConnectionInfo implementation
//-------------------------------------------------------

void MapInfoConnectionInfo::validate ()
{
    if (m_connection == NULL)
        throw FdoException::Create (NlsMsgGetMain(FDO_NLSID(MAPINFOPROVIDER_NO_CONNECTION)));
}

FdoString* MapInfoConnectionInfo::GetDirectory ()
{
    validate ();
    return (m_directory == L"" ? NULL : (FdoString*)m_directory);
}

FdoString* MapInfoConnectionInfo::GetFile ()
{
    validate ();
    return (m_file == L"" ? NULL : (FdoString*)m_file);
}

FdoString* MapInfoConnectionInfo::GetDataStore ()
{
    validate ();
    if (m_file.GetLength() > 0)
        return (FdoString*)m_file;
    else if (m_directory.GetLength() > 0)
        return (FdoString*)m_directory;
    else
        return L"";
}

// Returns the name of the feature provider.
FdoString* MapInfoConnectionInfo::GetProviderName()
{
    validate ();
    return MAPINFO_PROVIDER_NAME;
}

// Returns the provider's display name
FdoString* MapInfoConnectionInfo::GetProviderDisplayName()
{
    validate ();
    return NlsMsgGetMain(MAPINFO_PROVIDER_DISPLAY_NAME, MAPINFO_PROVIDER_DEFAULT_DISPLAY_NAME);
}

// Returns the description of the feature provider.
FdoString* MapInfoConnectionInfo::GetProviderDescription()
{
    validate ();
    return NlsMsgGetMain(MAPINFO_PROVIDER_DESCRIPTION, MAPINFO_PROVIDER_DEFAULT_DESCRIPTION);
}


// Returns the version of the feature provider.
FdoString* MapInfoConnectionInfo::GetProviderVersion()
{
    validate ();
    return MAPINFO_PROVIDER_VERSION;
}


// Returns the version of the Feature Data Objects specification
// this provider conforms to.
FdoString* MapInfoConnectionInfo::GetFeatureDataObjectsVersion()
{
    validate ();
    return MAPINFO_FDO_VERSION;
}


// Returns the IConnectionPropertyDictionary interface that can be used
// to dynamically query and set the properties required to establish a
// connection.
FdoIConnectionPropertyDictionary* MapInfoConnectionInfo::GetConnectionProperties()
{
    if (m_propertyDictionary == NULL)
    {
        m_propertyDictionary = new FdoCommonConnPropDictionary (m_connection);

        // Define all the connection properties:
        char* mbPropName = NULL;
        wide_to_multibyte(mbPropName, CONNECTIONPROPERTY_DEFAULT_FILE_LOCATION);
        FdoPtr<ConnectionProperty> property = new ConnectionProperty (CONNECTIONPROPERTY_DEFAULT_FILE_LOCATION,
                NlsMsgGetMain(MAPINFOPROVIDER_PROP_NAME_DEFAULT_FILE_LOCATION, mbPropName),
                EMPTY_VALUE, true, false, false, true, true, false, false, 0, NULL);
        m_propertyDictionary->AddProperty(property);
    }
    return (FDO_SAFE_ADDREF(m_propertyDictionary.p));
}

// Returns the provider type. A provider can be a file-based, database-based or
// web-based provider. The valid values the function may return are defined in
// the enumeration FdoProviderDatastoreType. The enumeration includes the following
// values: FdoProviderDatastoreType_Unknown, FdoProviderDatastoreType_File,
// FdoProviderDatastoreType_DatabaseServer, FdoProviderDatastoreType_WebServer.
FdoProviderDatastoreType MapInfoConnectionInfo::GetProviderDatastoreType()
{
    return FdoProviderDatastoreType_File;
}

// File-based providers depend on a various files. This function returns a list
// of fully qualified dependend file names. The return parameter will be NULL if
// the provider is not a file-based provider.
FdoStringCollection* MapInfoConnectionInfo::GetDependentFileNames()
{
#pragma message("TODO: Finish MapInfoConnectionInfo::GetDependentFileNames.")
    // If the connection is not yet open return NULL.
    if (m_connection->GetConnectionState() != FdoConnectionState_Open)
        return NULL;

    if (m_dependentFiles == NULL)
    {
        m_dependentFiles = FdoStringCollection::Create();
        const wchar_t* userPath = m_propertyDictionary->GetProperty(CONNECTIONPROPERTY_DEFAULT_FILE_LOCATION);
        if (FdoCommonFile::IsAbsolutePath(userPath))
            m_dependentFiles->Add(userPath);
        else
        {
            const wchar_t* userPath1 = FdoCommonFile::GetAbsolutePath(userPath);
            m_dependentFiles->Add(userPath1);
        }
    }
    return (FDO_SAFE_ADDREF(m_dependentFiles.p));
}

void MapInfoConnectionInfo::InitConnectionPaths()
{
    FdoStringP location = m_propertyDictionary->GetProperty (CONNECTIONPROPERTY_DEFAULT_FILE_LOCATION);

#ifdef _WIN32
    location = location.Replace(L"/", L"\\");
    FdoString* plocation = (FdoString*)location;
    if (plocation != NULL)
    {
        bool isRemote = (location.GetLength () > 2 && plocation[0] == L'\\' && plocation[1] == L'\\');
        location = location.Replace (L"\\\\", L"\\");
        if (isRemote == true)
            location = (FdoStringP)L"\\" + location;
    }
#else
    location = location.Replace(L"\\", L"/");
    location = location.Replace(L"//", L"/");
#endif

    // make a copy to play around with
    wchar_t* dir = (wchar_t*)alloca (sizeof (wchar_t) *(wcslen (location) + 2)); // 2 because we may need to add delimiter
    wcscpy (dir, location);
    FdoCommonStringUtil::StringTrim (dir);
    location = dir;
    size_t length = wcslen (dir);

    // store the file and/or directory provided:
    if (!FdoCommonFile::FileExists (dir))
    {
        if (length > wcslen (MAP_EXTENSION))
        {
            // is this a file or a folder?
            if (0 == FdoCommonStringUtil::StringCompareNoCase (MAP_EXTENSION, &dir[length - wcslen (MAP_EXTENSION)]))
            {   // presumably it's a file
                m_file = dir;
                m_directory = L"";
                wchar_t* delim = wcsrchr(dir, FILE_PATH_DELIMITER);
                if (delim == NULL)
                {
                    // Set to current directory if none specified:
                    dir = (wchar_t*)alloca(sizeof(wchar_t)*3);
                    dir[0] = L'.';
                    dir[1] = FILE_PATH_DELIMITER;
                    dir[2] = L'\0';
                }
                else
                {
                    *(++delim) = L'\0';
                }

                m_directory = dir;
            }
            else
            {
                m_directory = dir;
                m_file = L"";
            }
        }
    }
    else if (FdoCommonFile::IsDirectory(dir))
        m_file = L"";
    else  // user specified a single file to connect to
    {
        m_file = dir;

        wchar_t* delim = wcsrchr(dir, FILE_PATH_DELIMITER);
        if (delim == NULL)
        {
            // Set to current directory if none specified:
            dir = (wchar_t*)alloca(sizeof(wchar_t)*3);
            dir[0] = L'.';
            dir[1] = FILE_PATH_DELIMITER;
            dir[2] = L'\0';
        }
        else
        {
            *(++delim) = L'\0';
        }

        m_directory = dir;
    }

    if (NULL == GetFile ())
    {
        // strip off a wrong delimiter
        if (length == 0)
        {
            // Set to current directory if none specified:
            dir = (wchar_t*)alloca(sizeof(wchar_t)*3);
            dir[0] = L'.';
            dir[1] = FILE_PATH_DELIMITER;
            dir[2] = L'\0';
            length = 2;
        }

        // add the delimiter if not already present
        if (FILE_PATH_DELIMITER != dir[length - 1])
        {
            dir[length] = FILE_PATH_DELIMITER;
            dir[length + 1] = L'\0';
        }

        // Store the directory:
        m_directory = dir;
    }

    if (NULL != GetDirectory () && !FdoCommonFile::FileExists (GetDirectory()))
        throw FdoException::Create (NlsMsgGetMain(MAPINFOPROVIDER_NONEXISTING_DIR, "The directory '%1$ls' does not exist.", GetDirectory()));
    if (NULL != GetFile () && !FdoCommonFile::FileExists (GetFile ()))
        throw FdoException::Create (NlsMsgGetMain(MAPINFOPROVIDER_NONEXISTING_FILE, "The File '%1$ls' does not exist.", GetFile()));
}
